package org.flexthinker.binding.bean
{
    import org.flexthinker.binding.form.FormModel;

    /**
     * Uses a <code>FormModel</code> instance
     * to address ActionScript Beans properties of source objects.
     *
     * @see org.flexthinker.binding.bean.PropertyHelper
     * @see org.flexthinker.binding.form.FormModel
     *
     */
    public class FormModelProperty extends PropertyHelper
    {
        public function FormModelProperty(source:FormModel, propertyName:String)
        {
            super(source, propertyName);
            throwIfInvalidPath();
        }


        public static function create(path:String):FormModelProperty
        {
            return new FormModelProperty(null, path);
        }


        override public function getValue():Object
        {
            throwIfSourceNotSet();
            return FormModel(getSource()).getValueModel(getPath()).getValue();
        }


        override public function setValue(value:Object):void
        {
            throwIfSourceNotSet();
            FormModel(getSource()).getValueModel(getPath()).setValue(value);
        }


        override public function setSource(value:Object):void
        {
            super.setSource(value);

            watchChangesInFormModelProperty();
        }


        // ---------------------
        //    internal methods
        // ---------------------

        private function throwIfInvalidPath():void
        {
            if (getPath() && getPath().indexOf(".") >= 0)
            {
                throw new ArgumentError("Nested properties not allowed with FormModel source object");
            }
        }

        private function throwIfSourceNotSet():void
        {
            if ( getSource() == null )
            {
                throw new Error("Please call setSource() first before calling getValue() or setValue()");
            }
        }

        private function watchChangesInFormModelProperty():void
        {
            resetWatchers();

            listenTo(FormModel(getSource()).getValueModel(getPath()));
        }


    }
}
